package com.spdd.mt.common.thread;

import cn.hutool.core.thread.ThreadFactoryBuilder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.concurrent.*;

/**
 * 线程池
 *
 * @author shanfeilong
 */
@Slf4j
@Service
public class ThreadServiceImpl implements ThreadService {

    public ThreadServiceImpl() {
        ThreadPoolExecutor commonThreadPoolExecutor = new ThreadPoolExecutor(
                10,
                10,
                60,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(),
                new ThreadFactoryBuilder().setNamePrefix(ThreadPoolTypeEnum.COMMON.getMessage() + "-%d").build());
        executorMap.put(ThreadPoolTypeEnum.COMMON.getCode(), commonThreadPoolExecutor);

        // 延迟线程池
        scheduledExecutorService = Executors.newScheduledThreadPool(10);
    }

    /** 线程池Map */
    private final ConcurrentHashMap<Integer, ThreadPoolExecutor> executorMap = new ConcurrentHashMap<>();

    /** 延迟线程池 */
    private final ScheduledExecutorService scheduledExecutorService;

    /**
     * 提交任务
     *
     * @param threadPoolEnum 线程池类型
     * @param task           Runnable
     */
    @Override
    public void submit(ThreadPoolTypeEnum threadPoolEnum, Runnable task) {
        try {
            ThreadPoolExecutor threadPoolExecutor = executorMap.get(threadPoolEnum.getCode());

            if (threadPoolExecutor == null) {
                log.error(String.format("线程池提交:%s 线程池不存在", threadPoolEnum));
                return;
            }

            // log.info(String.format("线程池提交:%s-%s", threadPoolEnum, getExecutorInfo(threadPoolEnum)));

            threadPoolExecutor.submit(() -> {
                        try {
                            task.run();
                        } catch (Exception e) {
                            log.error("线程池线程执行异常", e);
                        }
                    }
            );
        } catch (Exception e) {
            log.error(String.format("线程池提交异常,%s", threadPoolEnum.getMessage()), e);
        }
    }

    /**
     * 提交任务(延迟执行)
     *
     * @param task                        Runnable
     * @param delayedExecutionMillisecond 延迟处理的毫秒(如果执行的时间小于执行时间则sleep,如果大于等于执行时间则立即执行)
     */
    @Override
    public void submitDelayedExecution(Runnable task, long delayedExecutionMillisecond) {
        try {
            log.info(String.format("延迟线程池提交:%s", delayedExecutionMillisecond));

            scheduledExecutorService.schedule(
                    () -> {
                        try {
                            task.run();
                        } catch (Exception e) {
                            log.error("延迟线程池执行异常", e);
                        }
                    },
                    delayedExecutionMillisecond,
                    TimeUnit.MILLISECONDS);
        } catch (Exception e) {
            log.error("延迟线程池提交异常", e);
        }
    }

    /**
     * 获取线程池信息
     *
     * @param threadPoolEnum 线程池类型
     * @return ThreadPoolInfoDto
     */
    @Override
    public ThreadPoolInfo getExecutorInfo(ThreadPoolTypeEnum threadPoolEnum) {
        ThreadPoolInfo threadPoolInfoDto = new ThreadPoolInfo();

        threadPoolInfoDto.setPoolName(threadPoolEnum.name());
        threadPoolInfoDto.setCorePoolSize(executorMap.get(threadPoolEnum.getCode()).getCorePoolSize());
        threadPoolInfoDto.setMaximumPoolSize(executorMap.get(threadPoolEnum.getCode()).getMaximumPoolSize());
        threadPoolInfoDto.setActiveCount(executorMap.get(threadPoolEnum.getCode()).getActiveCount());
        threadPoolInfoDto.setQueueSize(executorMap.get(threadPoolEnum.getCode()).getQueue().size());
        threadPoolInfoDto.setPoolSize(executorMap.get(threadPoolEnum.getCode()).getPoolSize());
        threadPoolInfoDto.setCompletedTaskCount(executorMap.get(threadPoolEnum.getCode()).getCompletedTaskCount());

        return threadPoolInfoDto;
    }
}
